import url from "@ohos.url";
import { HANDLER_FUNCTION } from "./Constant";
import { RESTFulDeclare, TYPE } from "./Type";

export interface Body {}

export enum Method {
  GET = "GET",
  POST = "POST",
  PUT = "PUT",
  DELETE = "DELETE",
  HEAD = "HEAD",
  PATCH = "PATCH",
  OPTIONS = "OPTIONS",
  TRACE = "TRACE",
  CONNECT = "CONNECT"
}

export class Request {
  readonly URL: url.URL
  readonly header: Map<string, string>
  readonly body

  readonly method: Method
  readonly query: Record<string, string | string[]>

  constructor(url: url.URL, method: Method, header: Map<string, string>, query: Record<string, string | string[]>,
    body: Body) {
    this.URL = url;
    this.method = method;
    this.header = header;
    this.query = query;
    this.body = body;
  }

  static createBuild(): RequestBuild {
    return new RequestBuild();
  }
}

export class RequestBuild {
  private _url: url.URL;
  private _method: Method;
  private _header: Map<string, string> = new Map();
  private _query: Record<string, string | string[]> = {};
  private _body: Body;

  constructor() {
    this[HANDLER_FUNCTION] = (declares: Map<number, RESTFulDeclare> | undefined, args: any[]) => {
      if (!declares) {
        return
      }
      args.forEach((arg, index) => {
        let declare = declares.get(index);
        if (!declare) {
          return
        }
        if (declare.type == TYPE.QUERY) {
          this._query[declare.key] = arg + '';
        } else if (declare.type == TYPE.QUERYS) {
          let argMap = arg as Map<string, string>;
          argMap.forEach((value, key) => {
            this._query[key] = value + '';
          });
        } else if (declare.type == TYPE.HEADER) {
          this._header.set(declare.key, arg + '');
        } else if (declare.type == TYPE.HEADERS) {
          let argMap = arg as Map<string, string>;
          argMap.forEach((value, key) => {
            this._header.set(key + '', value + '');
          });
        } else if (declare.type == TYPE.PATH) {
          this._url.pathname = this._url.pathname.replace(`{${declare.key}}`, arg + '');
        }
      })
    }
    this[HANDLER_FUNCTION] = (headers: Record<string, string>) => {
      Object.keys(headers.content).forEach(key => {
        this._header.set(key, headers.content[key]);
      })
    }
  }

  set url(value: url.URL) {
    this._url = value;
  }

  set method(value: Method) {
    this._method = value;
  }

  set body(value: Body) {
    this._body = value;
  }

  build(): Request {
    return new Request(this._url, this._method, this._header, this._query, this._body);
  }
}